package com.example.util;

import com.example.thread.RequestProcessor4;
import com.example.entity.Host;
import server.*;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 封装不同版本手写tomcat 启动
 *
 * @author kangshuai
 */
public class TomcatUtil {

    private static Map<String, HttpServlet> servletMap = new HashMap<String, HttpServlet>();

    private static Host host = new Host();


    /**
     * 完成M 1.0版本
     * 需求：浏览器请求http://localhost:8080,返回一个固定的字符串到页面"Hello Minicat!"
     *
     * @throws Exception
     */
    public static void tomcatVersionOne() throws Exception {
        ServerSocket serverSocket = new ServerSocket(host.getPort());
        while (true) {
            Socket socket = serverSocket.accept();
            // 有了socket，接收到请求，获取输出流
            OutputStream outputStream = socket.getOutputStream();
            String data = "Hello Minicat!";
            outputStream.write((HttpProtocolUtil.getHttpHeader200(data.length()) + data).getBytes());
            socket.close();
        }
    }

    /**
     * 完成 2.0版本
     * 需求：封装Request和Response对象，返回html静态资源文件
     */
    public static void tomcatVersionTwo() throws Exception {

        ServerSocket serverSocket = new ServerSocket(host.getPort());

        while (true) {
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();

            // 封装Request对象和Response对象
            Request request = new Request(inputStream);
            Response response = new Response(socket.getOutputStream());

            response.outputHtml(request.getUrl());
            socket.close();
        }
    }

    /**
     * 完成 3.0版本
     * 需求：多线程改造
     */
    public static void tomcatVersionThreeThread() throws Exception {

        ServerSocket serverSocket = new ServerSocket(host.getPort());

        while (true) {
            Socket socket = serverSocket.accept();
            RequestProcessor requestProcessor = new RequestProcessor(socket, servletMap);
            requestProcessor.start();
        }
    }

    /**
     * 完成 3.0版本
     * 需求：多线程改造
     */
    public static void tomcatVersionThree() throws Exception {

        ServerSocket serverSocket = new ServerSocket(host.getPort());

        while (true) {
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();

            Request request = new Request(inputStream);
            Response response = new Response(socket.getOutputStream());
            HttpServlet httpServlet = servletMap.get(request.getUrl());
            if (httpServlet == null) {
                response.outputHtml(request.getUrl());
            } else {
                httpServlet.service(request, response);
            }
            socket.close();
        }
    }

    /**
     * 完成 3.0版本
     * 需求：多线程改造 - 线程池
     */
    public static void tomcatVersionThreeThreadPool() throws Exception {

        ThreadPoolExecutor threadPoolExecutor = threadPoolExecutorHandle();

        ServerSocket serverSocket = new ServerSocket(host.getPort());

        while (true) {
            Socket socket = serverSocket.accept();
            RequestProcessor requestProcessor = new RequestProcessor(socket, servletMap);

            threadPoolExecutor.execute(requestProcessor);
        }
    }


    /**
     * 完成 4.0版本
     * 需求：自定义webapps目录
     */
    public static void tomcatVersionFour() throws Exception {

        ThreadPoolExecutor threadPoolExecutor = threadPoolExecutorHandle();

        Map<String, Host> hostMap = XmlHandleUtil.initHostMap();
        int port = XmlHandleUtil.initPort();

        ServerSocket serverSocket = new ServerSocket(port);

        while (true) {
            Socket socket = serverSocket.accept();
            RequestProcessor4 requestProcessor = new RequestProcessor4(socket, hostMap);
            threadPoolExecutor.execute(requestProcessor);
        }
    }

    /**
     * 抽取线程池方法
     *
     * @return
     * @throws Exception
     */
    private static ThreadPoolExecutor threadPoolExecutorHandle() throws Exception {
        int corePoolSize = 10;
        int maximumPoolSize = 50;
        long keepAliveTime = 100L;
        TimeUnit unit = TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();


        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler);

        return threadPoolExecutor;
    }

}
